//! \file QueueList_TODO.h
//! \brief Defines the <code>fullsail_ai::data_structures::QueueList</code> class template
//! implementation.
//! \author Cromwell D. Enage
#ifndef _FULLSAIL_AI_FUNDAMENTALS_QUEUELIST_TODO_H_
#define _FULLSAIL_AI_FUNDAMENTALS_QUEUELIST_TODO_H_

namespace fullsail_ai { namespace fundamentals {

	//! \todo
	//!   - Complete the definition of the <code>QueueList::Iterator</code> pre-increment operator.
	//!   - Complete the definition of the <code>QueueList::Iterator</code> dereference operator.
	//!   - Define the <code>QueueList</code> constructor.
	//!   - Define the <code>QueueList</code> destructor.
	//!   - Define the <code>QueueList</code> methods.

	template <typename T>
	QueueList<T>::QueueList()
	{
		front = NULL;
		back = NULL;
	}

	template <typename T>
	QueueList<T>::~QueueList()
	{
		removeAll();
	}

	template <typename T>
	bool typename QueueList<T>::isEmpty() const
	{
		if (front == NULL && back == NULL)
			return true;
		else
			return false;
	}

	template <typename T>
	T typename QueueList<T>::getFront() const
	{
		return front->data;
	}

	template <typename T>
	void typename QueueList<T>::removeAll()
	{
		while (front != NULL)
		{
			dequeue();
		}
	}

	template <typename T>
	void typename QueueList<T>::dequeue()
	{
		Node *tempFront = front;
		if (back == front)
		{
			delete front;
			front = NULL;
			back = NULL;
			return;
		}
		
		if (front != NULL)
		{
			front = front->next;
			delete tempFront;
			return;
		}
	}

	template <typename T>
	void typename QueueList<T>::enqueue(T element)
	{
		Node *tempNewNode = new Node(element);
		if (front == NULL && back == front)
		{
			front = tempNewNode;
			back = front;
		}
		else
		{
			if (back != NULL)
			{
				back->next = tempNewNode;
				back = tempNewNode;
			}
			else
			{
				back = tempNewNode;
				tempNewNode->next = NULL;
			}
		}
	}

	template <typename T>
	bool typename QueueList<T>::contains(T element) const
	{	
		Node *tempCurNode = front;
		while (true)
		{	
			if (tempCurNode->data == element)
				return true;
			else
				tempCurNode = tempCurNode->next;

			if (tempCurNode == NULL)
				return false;
		}
		return false;
	}

	template <typename T>
	void typename QueueList<T>::remove(T element)
	{
		if (isEmpty())
			return;

		Node *tempCurNode = front;
		Node *tempPrevNode = NULL;
		while (true)
		{
			// delete the only element in the queue
			if (front == back && front->data == element)
			{
				delete front;
				front = NULL;
				back = NULL;
				return;
			}
			// delete the last element in the queue
			else if (tempCurNode == back && tempCurNode->data == element)
			{
				delete tempCurNode;
				back = NULL;
				tempPrevNode->next = NULL;
				return;
			}
			// delete the first element in the queue
			else if (tempCurNode == front && tempCurNode->data == element)
			{
				front = front->next;
				delete tempCurNode;
				return;
			}
			// delete an element in the middle of the queue
			else if (tempCurNode != front && tempCurNode != back && tempCurNode->data == element)
			{
				tempPrevNode->next = tempCurNode->next;
				delete tempCurNode;
				return;
			}
			else
			{
				if (tempCurNode == back)
					return;
				else
				{
					tempPrevNode = tempCurNode;
					if (tempCurNode->next != NULL)
						tempCurNode = tempCurNode->next;
					else
						return;
				}
			}
		}
	}

	template <typename T>
	typename QueueList<T>::Iterator& QueueList<T>::Iterator::operator++()
	{
		// TODO: Complete the definition of this operator.
		currentNode = currentNode->next;
		return *this;
	}

	template <typename T>
	T QueueList<T>::Iterator::operator*() const
	{
		// TODO: Complete the definition of this operator.
		return currentNode->data;
	}


}}  // namespace fullsail_ai::fundamentals

#endif  // _FULLSAIL_AI_FUNDAMENTALS_QUEUELIST_TODO_H_

